﻿using System;
using UnityEngine;

/// <summary>
/// 寻路方向
/// </summary>
public enum PathDir
{
	/// <summary>
	/// 上下左右4个方向
	/// </summary>
	FourDir,

	/// <summary>
	/// 上下左右+斜对角8个方向
	/// </summary>
	EightDir
}

public enum DrawNodeType
{
	OpenNode,
	CloseNode,
}

public class AStarGrid
{
	private bool isDirty;
	public bool IsDirty
	{
		get { return isDirty; }
		private set { isDirty = value; }
	}

	private int Row;
	private int Col;

	private float originX;
	private float originY;
	private float nodeSize;
	private LayerMask WallLayer;

	private AStarNode[,] grid;

	public event Action OnGridChange;

	/// <summary>
	/// 画墙
	/// </summary>
	public event Action<AStarNode> OnDrawWall;

	public AStarGrid(int row, int col, float oriX, float oriY, float width, LayerMask layerMask)
	{
		this.Row = row;
		this.Col = col;
		originX = oriX;
		originY = oriY;
		nodeSize = width;
		WallLayer = layerMask;

		grid = new AStarNode[Col, Row];

		InitGrid();
	}

	/// <summary>
	/// 初始化网格
	/// </summary>
	public void InitGrid()
	{
		for (int i = 0; i < Col; i++)
		{
			for (int j = 0; j < Row; j++)
			{
				AStarNode node = new AStarNode();
				node.Index = new IntVec2(i, j);
				node.Position = GetNodeWorldPosByNodeIndex(node.Index);
				
//				if (Physics.CheckSphere(node.Position, nodeSize * 0.5f - 0.1f, WallLayer))
				RaycastHit2D hitInfo = Physics2D.CircleCast(node.Position, nodeSize*0.5f - 0.1f, Vector2.zero, 0, WallLayer);
				if (hitInfo.collider != null)
				{
					node.CanMove = false;
					if (OnDrawWall != null)
					{
						OnDrawWall(node);
					}
				}

				grid[i, j] = node;
			}
		}
	}

	/// <summary>
	/// 计算消耗()
	/// </summary>
	/// <param name="a"></param>
	/// <param name="b"></param>
	/// <returns></returns>
	public int CalcuteCost(AStarNode a, AStarNode b)
	{
		int deltaX = Math.Abs(a.Index.X - b.Index.X);
		int deltaY = Math.Abs(a.Index.Y - b.Index.Y);
		return deltaX + deltaY;
	}

	/// <summary>
	/// 根据世界坐标获取Node
	/// </summary>
	/// <param name="pos"></param>
	/// <returns></returns>
	public AStarNode GetNodeByWorldPos(Vector3 pos)
	{
		IntVec2 p = new IntVec2();
		p.X = (int)((pos.x - originX) / nodeSize);
		p.Y = (int)((pos.y - originY) / nodeSize);
		AStarNode node = GetNode(p.X, p.Y);

		return node;
	}

	/// <summary>
	/// 获取Node的世界坐标
	/// </summary>
	/// <param name="index"></param>
	/// <returns></returns>
	private Vector3 GetNodeWorldPosByNodeIndex(IntVec2 index)
	{
		return new Vector3(originX + (index.X + 0.5f) * nodeSize, originY + (index.Y + 0.5f) * nodeSize, 0);
	}

	public AStarNode GetNode(IntVec2 pos)
	{
		AStarNode node = null;
		if (WithInBorder(pos.X, pos.Y))
		{
			node = grid[pos.X, pos.Y];
		}

		return node;
	}

	public AStarNode GetNode(int x, int y) {
		AStarNode node = null;
		if (WithInBorder(x, y)) {
			node = grid[x, y];
		}

		return node;
	}

	public void SetDirty(AStarNode node)
	{
		if (!IsDirty)
		{
			IsDirty = true;
		}

		if (OnGridChange != null)
		{
			OnGridChange();
		}

		if (OnDrawWall != null)
		{
			OnDrawWall(node);
		}
	}

	public void ClearDirty()
	{
		IsDirty = false;
	}

	/// <summary>
	/// 判断是否越界
	/// </summary>
	/// <param name="x"></param>
	/// <param name="y"></param>
	/// <returns></returns>
	public bool WithInBorder(int x, int y) {
		return (x >= 0 && x < Col) && (y >= 0 && y < Row);
	}

	public bool WithInBorder(IntVec2 vec) {
		return (vec.X >= 0 && vec.X < Col) && (vec.Y >= 0 && vec.Y < Row);
	}
}
